package com.qd.push.mq.httpmsg;

import com.cdqidi.exception.ApiException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qd.common.panda.constant.PandaConstant;
import com.qd.common.panda.domain.entity.hk.HkParkOrderDTO;
import com.qd.common.panda.domain.entity.hk.mq.HttpMsgData;
import com.qd.push.config.ExecutorConfig;
import com.qd.push.config.PushConfig;
import com.qd.push.log.SendLogsService;
import com.qd.push.model.HkPushLog;
import com.qd.push.model.HkPushReq;
import com.qd.push.model.HkPushResp;
import com.qd.push.service.HkParkOrderService;
import com.qd.push.service.OperationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.concurrent.ExecutorService;
import java.util.function.Consumer;

/**
 * 〈小程序〉<br>
 *
 * @author sjk
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class HkMsgConsumer {

    private final ObjectMapper objectMapper;
    private final OperationService operationService;
    private final SendLogsService sendLogsService;
    private final HkMsgProducer hkMsgProducer;
    private final ExecutorConfig executorConfig;
    private final HkParkOrderService hkParkOrderService;
    @Resource
    private PushConfig pushConfig;

    /**
     * 接收消息
     */
    @Bean
    public Consumer<String> sendHttp() {
        return this::receive;
    }

    public void receive(String payload) {
        LocalDateTime receiveTime = LocalDateTime.now();
        HttpMsgData<HkParkOrderDTO> httpMsgData;
        try {
            httpMsgData = objectMapper.readValue(payload, new TypeReference<>() {
            });
        } catch (IOException e) {
            throw new ApiException(e);
        }
        ExecutorService executorService = executorConfig.getExecutorService("default");
        executorService.submit(() -> {
            long startTime = System.currentTimeMillis();
            HkPushReq hkPushReq = new HkPushReq();
            HkPushResp hkPushResp = new HkPushResp();
            HkPushLog hkPushLog = new HkPushLog();
            HkParkOrderDTO reqData = httpMsgData.getReqData();
            operationService.send(reqData, hkPushLog, hkPushReq, hkPushResp);
            if (StringUtils.hasLength(hkPushResp.getRespParam())) {
                send(httpMsgData);
            } else {
                hkPushResp = null;
            }
            long endTime = System.currentTimeMillis();
            hkPushLog.setReceiveTime(receiveTime);
            hkPushLog.setBid(reqData.getBid());
            if (StringUtils.hasLength(reqData.getInUnid())) {
                hkPushLog.setInUnid(reqData.getInUnid());
            }
            if (StringUtils.hasLength(reqData.getBillCode())) {
                hkPushLog.setBillCode(reqData.getBillCode());
            }
            hkPushLog.setClassification(PandaConstant.CLASSIFICATION_HK);
            if (reqData.getOrderType().equals(PandaConstant.HK_ORDER_TYPE_1)) {
                hkPushLog.setChildClassification(PandaConstant.CHILD_CLASSIFICATION_HK_PAY_NOTICE);
            }
            if (reqData.getOrderType().equals(PandaConstant.HK_ORDER_TYPE_2)) {
                hkPushLog.setChildClassification(PandaConstant.CHILD_CLASSIFICATION_HK_PAY_ARREARS_FEE);
                hkParkOrderService.updateById(reqData.getOrderLogId(), reqData.getBillCode());
            }
            hkPushLog.setSendTime(LocalDateTime.now());
            hkPushLog.setTimeConsumer(endTime - startTime);
            sendLogsService.saveSendLog(hkPushLog, hkPushReq, hkPushResp);
            httpMsgData.freeData();
        });

    }


    public void send(HttpMsgData<HkParkOrderDTO> httpMsgData) {
        //发生了异常，进入延时队列，稍后重试
        Integer retryCount = httpMsgData.getRetryCount();
        if (null == retryCount) {
            retryCount = 1;
        }
        Integer delayTime = pushConfig.getDelayTime(retryCount);
        if (null != delayTime) {
            httpMsgData.setRetryCount(retryCount + 1);
            try {
                String payLoad = objectMapper.writeValueAsString(httpMsgData);
                hkMsgProducer.sender(payLoad, delayTime);
            } catch (JsonProcessingException ignored) {
            }
        }
    }
}
